package com.cdp.web.controller.system.report;

import com.cdp.common.core.domain.AjaxResult;
import com.cdp.system.dto.PerformanceFifthDTO;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHeightRule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@RestController
@RequestMapping
public class TargetReportFifthController {

    private static final Logger LOGGER = LoggerFactory.getLogger(TargetReportFifthController.class);

    // 模板路径（目录）配置
    @Value("${filePython.upload-pkl-excel}")
    private String uploadPklExcelPath;

    // 文件输出目录配置
    @Value("${file.upload-dir}")
    private String fileUploadDir;

    /**
     * 生成目标性能预测报告（第五版）
     */
    @PostMapping("/make/report/target/performance/fifth")
    public AjaxResult makeTargetReportFifth(@RequestBody PerformanceFifthDTO makeReportDTO) {
        // 构造替换文本Map
        Map<String, String> textReplaceMap = buildTextReplaceMap(makeReportDTO);

        String templatePath = uploadPklExcelPath + "template5.docx";
        String directoryPath = fileUploadDir;

        try {
            // 创建输出目录（如果不存在）
            if (!Files.exists(Paths.get(directoryPath))) {
                Files.createDirectories(Paths.get(directoryPath));
            }

            try (InputStream is = new FileInputStream(templatePath);
                 XWPFDocument doc = new XWPFDocument(is)) {

                // 替换文本占位符
                replaceTextPlaceholders(doc, textReplaceMap);

                // 替换图片占位符，图片路径请替换为实际路径
                replaceImagePlaceholder(doc, "${imageUrl}",makeReportDTO.getImageUrl() );

                // 获取excel数据，替换表格内容
                List<List<String>> excelData = makeReportDTO.getExcelData();
                if (excelData == null || excelData.isEmpty()) {
                    return AjaxResult.error("excelData不能为空");
                }
                replaceTableDataByColumns(doc, excelData);

                // 生成唯一文件名并保存
                String fileName = generateUniqueFileName();
                String outPath = directoryPath + fileName;

                try (OutputStream os = new FileOutputStream(outPath)) {
                    doc.write(os);
                }

                LOGGER.info("报告生成成功: {}", outPath);
                return AjaxResult.success(outPath);
            }
        } catch (FileNotFoundException e) {
            LOGGER.error("文件未找到", e);
            return AjaxResult.error("文件未找到：" + e.getMessage());
        } catch (Exception e) {
            LOGGER.error("报告生成失败", e);
            return AjaxResult.error("报告生成失败：" + e.getMessage());
        }
    }


    /**
     * 构建文档中要替换的文本映射关系
     */
    private Map<String, String> buildTextReplaceMap(PerformanceFifthDTO dto) {
        Map<String, String> map = new HashMap<>();
        LocalDateTime nowDate = LocalDateTime.now();
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        map.put("${nowDate}", nowDate.format(dateFormatter));
        map.put("${model}", Optional.ofNullable(dto.getModel()).orElse(""));
        map.put("${target}", Optional.ofNullable(dto.getTarget()).orElse(""));
        map.put("${number}", Optional.ofNullable(dto.getNumber()).orElse(""));
        map.put("${detail}", Optional.ofNullable(dto.getDetail()).orElse(""));
        map.put("${percentage}", Optional.ofNullable(dto.getPercentage()).orElse(""));
        map.put("${r2}", Optional.ofNullable(dto.getR2()).orElse(""));
        map.put("${mse}", Optional.ofNullable(dto.getMse()).orElse(""));
        return map;
    }

    /**
     * 替换文档中所有文本占位符
     */
    private void replaceTextPlaceholders(XWPFDocument doc, Map<String, String> replaceMap) {
        // 替换段落文本
        for (XWPFParagraph paragraph : doc.getParagraphs()) {
            replaceInParagraph(paragraph, replaceMap);
        }

        // 替换表格中单元格的文本
        for (XWPFTable table : doc.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph paragraph : cell.getParagraphs()) {
                        replaceInParagraph(paragraph, replaceMap);
                    }
                }
            }
        }
    }
    private void replaceInParagraph(XWPFParagraph paragraph, Map<String, String> replaceMap) {
        List<XWPFRun> runs = paragraph.getRuns();
        StringBuilder fullText = new StringBuilder();

        // 拼接所有run的文本
        for (XWPFRun run : runs) {
            String text = run.getText(0);
            fullText.append(text == null ? "" : text);
        }

        String replacedText = fullText.toString();

        // 执行文本替换
        for (Map.Entry<String, String> entry : replaceMap.entrySet()) {
            if (replacedText.contains(entry.getKey())) {
                replacedText = replacedText.replace(entry.getKey(), entry.getValue());
            }
        }

        // 如果没有run，直接创建一个新的run写入替换文本
        if (runs == null || runs.isEmpty()) {
            XWPFRun newRun = paragraph.createRun();
            newRun.setText(replacedText);
            return;
        }

        // 保存第一个run的样式
        XWPFRun firstRun = runs.get(0);
        // 复制样式数据，具体复制哪些可根据需求定制
        String fontFamily = firstRun.getFontFamily();
        int fontSize = firstRun.getFontSize();
        boolean isBold = firstRun.isBold();
        boolean isItalic = firstRun.isItalic();
        String color = firstRun.getColor();

        // 删除原有所有run
        int runCount = runs.size();
        for (int i = runCount - 1; i >= 0; i--) {
            paragraph.removeRun(i);
        }

        // 新建run，写入替换后的文本
        XWPFRun newRun = paragraph.createRun();
        newRun.setText(replacedText);

        // 恢复样式
        if (fontFamily != null) {
            newRun.setFontFamily(fontFamily);
        }
        if (fontSize > 0) {
            newRun.setFontSize(fontSize);
        }
        newRun.setBold(isBold);
        newRun.setItalic(isItalic);
        if (color != null) {
            newRun.setColor(color);
        }
    }

    // 复制字体、颜色、粗细等run样式
    private void copyRunStyle(XWPFRun source, XWPFRun target) {
        target.setBold(source.isBold());
        target.setItalic(source.isItalic());
        target.setUnderline(source.getUnderline());
        target.setColor(source.getColor());
        target.setFontFamily(source.getFontFamily());
        target.setFontSize(source.getFontSize());
        target.setTextPosition(source.getTextPosition());
        // 你可以根据需要复制更多属性
    }

    /**
     * 替换单个段落中所有匹配占位符
     */
   /* private void replaceInParagraph(XWPFParagraph paragraph, Map<String, String> replaceMap) {
        StringBuilder fullText = new StringBuilder();
        List<XWPFRun> runs = paragraph.getRuns();

        // 拼接所有Run文本
        for (XWPFRun run : runs) {
            String text = run.getText(0);
            if (text != null) {
                fullText.append(text);
            }
        }

        String replacedText = fullText.toString();

        // 替换所有占位符
        for (Map.Entry<String, String> entry : replaceMap.entrySet()) {
            if (replacedText.contains(entry.getKey())) {
                replacedText = replacedText.replace(entry.getKey(), entry.getValue());
            }
        }

        // 清空旧Run
        int runCount = runs.size();
        for (int i = runCount - 1; i >= 0; i--) {
            paragraph.removeRun(i);
        }

        // 添加新Run写入替换后文本
        XWPFRun newRun = paragraph.createRun();
        newRun.setText(replacedText);
    }
*/
    /**
     * 替换图片占位符，支持png/jpeg格式
     */
    private void replaceImagePlaceholder(XWPFDocument doc, String placeholder, String imagePath) throws Exception {
        for (XWPFParagraph paragraph : doc.getParagraphs()) {
            List<XWPFRun> runs = paragraph.getRuns();
            for (int i = 0; i < runs.size(); i++) {
                XWPFRun run = runs.get(i);
                String text = run.getText(0);
                if (text != null && text.contains(placeholder)) {
                    // 清空文本占位符
                    run.setText("", 0);

                    // 读取图片输入流
                    try (InputStream is = new FileInputStream(imagePath)) {
                        run.addPicture(is,
                                XWPFDocument.PICTURE_TYPE_PNG,
                                imagePath,
                                Units.toEMU(300), // 宽度
                                Units.toEMU(300)); // 高度
                    }

                    // 替换完成跳出
                    return;
                }
            }
        }
    }
    /**
     * 替换表格数据，按列替换，且新增行
     * @param doc 文档对象
     * @param excelData 表格数据
     */
    private void replaceTableDataByColumns(XWPFDocument doc, List<List<String>> excelData) {
        if (doc.getTables().isEmpty()) {
            throw new IllegalArgumentException("模板中没有表格");
        }

        // 确保数据至少有5列，如果不足则补充空列
        while (excelData.size() < 6) {
            excelData.add(new ArrayList<>());
        }

        XWPFTable table = doc.getTables().get(0);

        // 求最大行数
        int maxRowCount = excelData.stream()
                .mapToInt(List::size)
                .max()
                .orElse(0);

        int templateRowCount = table.getNumberOfRows();

        // 不够行就新增
        for (int i = templateRowCount; i < maxRowCount; i++) {
            table.createRow();
        }

        for (int col = 0; col < excelData.size(); col++) {
            List<String> colData = excelData.get(col);

            for (int row = 0; row < maxRowCount; row++) {
                XWPFTableRow tableRow = table.getRow(row);

                // 设置固定高度为 5mm（约 284 Twips）
                tableRow.setHeight(284);
                tableRow.setHeightRule(TableRowHeightRule.EXACT);

                // 确保当前行有对应列单元格
                while (tableRow.getTableCells().size() <= col) {
                    tableRow.createCell();
                }

                XWPFTableCell cell = tableRow.getCell(col);

                // 清空旧内容
                cell.removeParagraph(0);

                // 写入新文本并设置字体样式为小四宋体（12pt）
                XWPFParagraph paragraph = cell.addParagraph();
                XWPFRun run = paragraph.createRun();

                // 处理空值情况，用"/"填充
                String text = row < colData.size() ? colData.get(row) : "";
                if (text == null || text.trim().isEmpty()) {
                    text = "/";
                }

                run.setText(text);
                run.setFontFamily("宋体");
                run.setFontSize(10); // 小四：12pt
            }
        }
    }

    /**
     * 生成唯一文件名
     */
    private String generateUniqueFileName() {
        long timestamp = System.currentTimeMillis();
        int randomNum = new Random().nextInt(10000);
        return timestamp + "_" + randomNum + ".docx";
    }
    /**
     * 按列替换Word表格数据
     */
/*    private void replaceTableDataByColumns(XWPFDocument doc, List<List<String>> excelData) {
        if (doc.getTables().isEmpty()) {
            throw new IllegalArgumentException("模板中没有表格");
        }

        XWPFTable table = doc.getTables().get(0);

        int maxRowCount = excelData.stream()
                .mapToInt(List::size)
                .max()
                .orElse(0);

        // 补充行数保证足够
        int currentRowCount = table.getNumberOfRows();
        for (int i = currentRowCount; i < maxRowCount; i++) {
            table.createRow();
        }

        // 遍历每列替换数据
        for (int col = 0; col < excelData.size(); col++) {
            List<String> colData = excelData.get(col);
            for (int row = 0; row < maxRowCount; row++) {
                XWPFTableRow tableRow = table.getRow(row);

                // 设置行高（可选）
                tableRow.setHeight(284);
                tableRow.getCtRow().addNewTrPr().addNewTrHeight().setVal(284);
                tableRow.getCtRow().getTrPr().getTrHeightList().get(0).setHRule(STHeightRule.Enum.forString("exact"));

                // 确保单元格数量足够
                while (tableRow.getTableCells().size() <= col) {
                    tableRow.createCell();
                }

                XWPFTableCell cell = tableRow.getCell(col);
                // 清空单元格所有段落
                int paraCount = cell.getParagraphs().size();
                for (int i = paraCount - 1; i >= 0; i--) {
                    cell.removeParagraph(i);
                }

                // 新建段落写入文本
                XWPFParagraph paragraph = cell.addParagraph();
                XWPFRun run = paragraph.createRun();
                String text = row < colData.size() ? colData.get(row) : "";
                run.setText(text);
                run.setFontFamily("宋体");
                run.setFontSize(10);
            }
        }
    }

    *//**
     * 生成唯一文件名，避免文件覆盖
     *//*
    private String generateUniqueFileName() {
        long timestamp = System.currentTimeMillis();
        int randomNum = new Random().nextInt(10000);
        return timestamp + "_" + randomNum + ".docx";
    }*/
}
